home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-06-19 | 18.5 KB | 742 lines |
- package symantec.itools.awt;
-
-
- import java.awt.Button;
- import java.awt.Component;
- import java.awt.Container;
- import java.awt.Event;
- import java.awt.Label;
- import java.awt.Panel;
- import java.awt.TextComponent;
- import java.util.Vector;
-
-
- /**
- * A Panel extension which provides for
- * tabbing between components and supporting certain key accelerations
- * by posting events provided by the user. Can be used directly or extended.
- * When extending from BaseTabbedPanel be sure to super()
- * during construction and to super.handleEvent(evt) from
- * handleEvent if you override it.
- * <p>
- * The tab focus order is based on the order in which the components were
- * positioned within the selected layout manager. Each component receives
- * focus in turn, but the mouse cursor is not relocated. Look at the Project
- * window to see the tab order of components within the KeyPressManagerPanel.
- * You can change the tab order by moving the component names in the Project
- * window list.
- * <p>
- * Components respond to default events when they receive focus. For example,
- * the TextField component displays text input from the keyboard, and the
- * Button component issues an action event when it is clicked.
- * <p>
- * Use KeyPressManagerPanel to create a panel whose elements can be tabbed
- * through, and specifically to:
- * <UL>
- * <DT>╖ create a subcontainer that organizes container space within an Applet,
- * Frame or Dialog container. This simplifies your component layout task.</DT>
- * <DT>╖ hold other specialized Panel containers.</DT>
- * </UL>
- * @version 1.0, Nov 26, 1996
- * @author Symantec
- */
-
- // 05/15/97 CAR Changed doTab to "deselect" the text of the text component being tabbed from
- // 03/03/97 RKM Fixed a bug in doTab, where it would tab to a hidden component
- // 03/13/97 RKM Added code in HandleEvent to handle return being hit in TextFields which
- // results in a Action being sent
- // 03/13/97 RKM Added ability to tab to TextComponents only, and defaulted it true for Mac
- // On platforms that support tabbing this is not needed, but on the Mac tabbing
- // would stop if you hit anything but a TextComponent - this seems a descent solution
- //
- // When encountering a non TextComponent on the Mac before defaulting to true:
- // Netscape - would not tab to the next component
- // Symantec - focus would be lost
- // Apple - tabbing works, but no focus is shown in non TextComponents and keys do nothing (ie List)
- // MW - same as Apple
-
- public class KeyPressManagerPanel
- extends Panel
- {
- //--------------------------------------------------
- // constants
- //--------------------------------------------------
-
- /**
- * A constant that indicates no modifier keys (SHIFT,CTRL) were pressed with a key.
- */
- public static final int PLAIN = 0;
- /**
- * A constant that indicates SHIFT was pressed with a key.
- */
- public static final int SHIFT = Event.SHIFT_MASK;
- /**
- * A constant that indicates CTRL was pressed with a key.
- */
- public static final int CTRL = Event.CTRL_MASK;
-
-
- //--------------------------------------------------
- // class variables
- //--------------------------------------------------
-
-
- //--------------------------------------------------
- // member variables
- //--------------------------------------------------
-
- Vector tabbed;
- Button defaultButton;
- Button cancelButton;
- Event defaultEvent;
- Event cancelEvent;
- Event fKeyEvents[];
- Container defaultDeliver;
- Container cancelDeliver;
- Container fKeyDeliver[];
- boolean bDefaultSetFocus;
- boolean bCancelSetFocus;
- boolean bTabHack;
- boolean bAutoTab;
- boolean bOnlyTabToTextComponents;
- Event eventLostFocus;
-
-
- //--------------------------------------------------
- // constructors
- //--------------------------------------------------
-
- /**
- * Constructs a Panel which handles key press events.
- */
- public KeyPressManagerPanel()
- {
- fKeyEvents = new Event[36];
- fKeyDeliver = new Container[36];
- bAutoTab = true;
- if (symantec.itools.lang.OS.isMacintosh())
- bOnlyTabToTextComponents = true;
- else
- bOnlyTabToTextComponents = false;
- resetKeyManager();
- }
-
-
- //--------------------------------------------------
- // accessor methods
- //--------------------------------------------------
-
- /**
- * Sets the automatic tab state. Note: this needs to be set before the
- * add() method is called.
- * @param bNewTabState new automatic tab state
- * @see #getAutoTabState
- * @see #add
- */
- public void setAutoTabState(boolean bNewTabState)
- {
- bAutoTab = bNewTabState;
- }
-
- /**
- * Gets the current automatic tab state.
- * @return current automatic tab state value
- * @see #setAutoTabState
- */
- public boolean getAutoTabState()
- {
- return bAutoTab;
- }
-
- /**
- * Sets whether tabs should only change focus to TextComponents.
- * This is defaulted to true on a Macintosh
- * @param bNewOnlyTabToTextComponents new tab to TextComponents only state
- * @see #getTabToTextComponetsOnly
- */
- public void setTabToTextComponetsOnly(boolean bNewOnlyTabToTextComponents)
- {
- bOnlyTabToTextComponents = bNewOnlyTabToTextComponents;
- }
-
- /**
- * Gets whether tabbing is to TextComponents only.
- * @return true if tabbing is to TextComponents only
- * @see #setTabToTextComponetsOnly
- */
- public boolean getTabToTextComponetsOnly()
- {
- return bOnlyTabToTextComponents;
- }
-
- //--------------------------------------------------
- // event methods
- //--------------------------------------------------
-
- /**
- * Processes events for this component.
- * This is a standard Java AWT method which gets called by the AWT
- * to handle this component's events. The default handler for
- * components dispatches to one of the following methods as needed:
- * action(), gotFocus(), lostFocus(), keyDown(), keyUp(), mouseEnter(),
- * mouseExit(), mouseMove(), mouseDrag(), mouseDown(), or mouseUp().
- *
- * @param evt the event to handle
- * @return true if the event was handled and no further action is needed,
- * false to pass the event to this component's parent
- * @see java.awt.Component#action
- * @see java.awt.Component#gotFocus
- * @see java.awt.Component#lostFocus
- * @see java.awt.Component#keyDown
- * @see java.awt.Component#keyUp
- * @see java.awt.Component#mouseEnter
- * @see java.awt.Component#mouseExit
- * @see java.awt.Component#mouseMove
- * @see java.awt.Component#mouseDrag
- * @see java.awt.Component#mouseDown
- * @see java.awt.Component#mouseUp
- */
- public synchronized boolean handleEvent(Event evt)
- {
- switch (evt.id)
- {
- case Event.ACTION_EVENT:
- //Has return been hit in a TextField
- if (evt.target instanceof java.awt.TextField)
- {
- //Make certain the TextField is in us (not one of our children)
- boolean itsOurs = false;
- int numChildren = countComponents();
- for (int i = 0;i< numChildren;i++)
- {
- Component testComponent = getComponent(i);
- if (testComponent != null && testComponent == evt.target)
- {
- itsOurs = true;
- break;
- }
- }
-
- if (itsOurs)
- {
- boolean buttonClicked = clickDefaultButton();
- if (buttonClicked)
- return true;
- }
- }
- break;
-
- case Event.KEY_ACTION:
- {
- int index = evt.key - Event.F1;
-
- switch (evt.modifiers)
- {
- case PLAIN:
- {
- break;
- }
- case SHIFT:
- {
- index += 12;
- break;
- }
- case CTRL:
- {
- index += 24;
- break;
- }
- default:
- {
- index = -1;
- break;
- }
- }
-
- if ((index > -1) && (index < 36))
- {
- if (fKeyEvents[index] != null)
- {
- deliverEventTo(fKeyEvents[index], fKeyDeliver[index]);
- return true;
- }
- }
-
- break;
- }
- case Event.KEY_PRESS:
- {
- bTabHack = false;
-
- if (keyPressed(evt))
- {
- return true;
- }
-
- break;
- }
- case Event.LOST_FOCUS:
- {
- if (evt.target instanceof TextComponent)
- {
- eventLostFocus = evt;
- bTabHack = true;
- }
-
- break;
- }
- case Event.KEY_RELEASE:
- {
- if (bTabHack)
- {
- bTabHack = false;
- eventLostFocus.key = evt.key;
- eventLostFocus.modifiers = evt.modifiers;
-
- if (keyPressed(eventLostFocus))
- {
- return true;
- }
- }
-
- break;
- }
- }//switch
-
- return super.handleEvent(evt);
- }
-
- boolean clickDefaultButton()
- {
- if (defaultButton != null)
- {
- if (defaultButton.isEnabled())
- {
- //???RKM??? Should we check if it is visible
- if (bDefaultSetFocus)
- {
- defaultButton.requestFocus();
- }
-
- deliverEventTo(defaultEvent, defaultDeliver);
-
- return true;
- }
- }
-
- return false;
- }
-
- boolean keyPressed(Event evt)
- {
- switch (evt.key)
- {
- case 9: // TAB:
- {
- if (evt.target instanceof Component)
- {
- return doTab((Component)evt.target, evt.modifiers);
- }
-
- return doTab((Component) this, evt.modifiers); // component not in list
- }
- case 10: // ENTER:
- {
- boolean buttonClicked = clickDefaultButton();
- if (buttonClicked)
- return true;
- break;
- }
- case 27: // ESC:
- {
- if (cancelButton != null)
- {
- if (cancelButton.isEnabled())
- {
- if (bCancelSetFocus)
- {
- cancelButton.requestFocus();
- }
-
- deliverEventTo(cancelEvent, cancelDeliver);
-
- return true;
- }
- }
-
- break;
- }
- }
-
- return false;
- }
-
-
- //--------------------------------------------------
- // class methods
- //--------------------------------------------------
-
-
- //--------------------------------------------------
- // memeber methods
- //--------------------------------------------------
-
- /**
- * Resets all KeyPressManager associations (default button, cancel
- * button, tab stop list).
- */
- public void resetKeyManager()
- {
- tabbed = new Vector();
- defaultButton = null;
- cancelButton = null;
- defaultEvent = null;
- cancelEvent = null;
- defaultDeliver = null;
- cancelDeliver = null;
- bDefaultSetFocus = false;
- bCancelSetFocus = false;
-
- for (int x = 0; x < 36; x++)
- {
- fKeyEvents[x] = null;
- fKeyDeliver[x] = null;
- }
- }
-
- /**
- * Adds a component to the end of this container.
- * This is a standard Java AWT method which gets called to add a
- * component to a container. The specified component is added to
- * the end of this container.
- * If auto-tab enabled (the default)
- * it also adds the component to the tab stop list.
- * @param component the component to add
- * @return the added component
- * @see java.awt.Container#remove
- */
- public Component add(Component component)
- {
- if(bAutoTab)
- {
- if (!(component instanceof Label))
- {
- setTabStop(component);
- }
- }
-
- return super.add(component);
- }
-
- /**
- * Removes Enter/Return key association with current default
- * button/event.
- * @see #setDefaultButton
- */
- public void removeDefaultButton()
- {
- defaultButton = null;
- defaultEvent = null;
- defaultDeliver = null;
- bDefaultSetFocus = false;
- }
-
-
- /**
- * Sets the components as the next tab stop in the list
- * components.
- * @param component the Component
- */
- public void setTabStop(Component component)
- {
- if (component != this)
- {
- tabbed.addElement(component);
- }
- }
-
- /**
- * Sets the button to press when the Enter or Return key
- * is pressed.
- * @param button the button to set as default
- * @see #removeDefaultButton
- */
- public void setDefaultButton(Button button)
- {
- setDefaultButton(button, new Event(button, Event.ACTION_EVENT, null), null, true);
- }
-
- /**
- * Associates a button and event with the Enter or Return
- * key press.
- * @param button the button to set as default
- * @param evt the event to delivered in response
- * @param deliverTo the container to deliver the event to
- * @param bSetFocus whether to set focus to the button before
- * delivering event
- * @see #removeDefaultButton
- */
- public void setDefaultButton(Button button, Event evt, Container deliverTo, boolean bSetFocus)
- {
- defaultButton = button;
- defaultEvent = evt;
- defaultDeliver = deliverTo;
- bDefaultSetFocus = bSetFocus;
- button.requestFocus();
- }
-
- /**
- * Sets the button to press when the Escape key is pressed.
- * @param button the button to set as Cancel
- * @see #removeCancelButton
- */
- public void setCancelButton(Button button)
- {
- setCancelButton(button, new Event(button, Event.ACTION_EVENT, null), null, true);
- }
-
- /**
- * Associates a button and event with the Escape key press.
- * @param button the button to set as Cancel
- * @param evt the event to delivered in response
- * @param deliverTo the container to deliver the event to
- * @param bSetFocus whether to set focus to the button before
- * delivering event
- * @see #removeCancelButton
- */
- public void setCancelButton(Button button, Event evt, Container deliverTo, boolean bSetFocus)
- {
- cancelButton = button;
- cancelEvent = evt;
- bCancelSetFocus = bSetFocus;
- cancelDeliver = deliverTo;
- }
-
- /**
- * Removes Escape key association with current Cancel button/event
- * @see #setCancelButton
- */
- public void removeCancelButton()
- {
- cancelButton = null;
- cancelEvent = null;
- cancelDeliver = null;
- bCancelSetFocus = false;
- }
-
- /**
- * Associates an event with a Function key press
- * @param fKey the Event.F1 - Event.F12 constant
- * @param evt the event to delivered in response
- * @param deliverTo the container to deliver the event to
- * @see #removeFKeyEvent
- */
- public void setFKeyEvent(int fKey, Event evt, Container deliverTo)
- {
- setFKeyEvent(fKey, PLAIN, evt, deliverTo);
- }
-
- /**
- * Removes association of an event with a Function key press
- * @param fKey the Event.F1 - Event.F12 constant
- * @see #setFKeyEvent
- */
- public void removeFKeyEvent(int fKey)
- {
- removeFKeyEvent(fKey, PLAIN);
- }
-
- /**
- * Associates an event with a Function key press
- * @param fKey the Event.F1 - Event.F12 constant
- * @param modifier PLAIN, SHIFT, or CTRL modifier
- * @param evt the event to delivered in response
- * @param deliverTo the container to deliver the event to
- * @see #removeFKeyEvent
- */
- public void setFKeyEvent(int fKey, int modifier, Event evt, Container deliverTo)
- {
- int index = fKey - Event.F1;
-
- if ((index < 0) || (index > 11))
- {
- return;
- }
-
- switch (modifier)
- {
- case PLAIN:
- {
- break;
- }
- case SHIFT:
- {
- index += 12;
- break;
- }
- case CTRL:
- {
- index += 24;
- break;
- }
- }
-
- fKeyEvents[index] = evt;
- fKeyDeliver[index] = deliverTo;
- }
-
- /**
- * Removes association of an event with a Function key press
- * @param fKey the Event.F1 - Event.F12 constant
- * @param modifier PLAIN, SHIFT, or CTRL modifier
- * @see #setFKeyEvent
- */
- public void removeFKeyEvent(int fKey, int modifier)
- {
- int index = fKey - Event.F1;
-
- if ((index < 0) || (index > 11))
- {
- return;
- }
-
- switch (modifier)
- {
- case PLAIN:
- {
- break;
- }
- case SHIFT:
- {
- index += 12;
- break;
- }
- case CTRL:
- {
- index += 24;
- break;
- }
- }
-
- fKeyEvents[index] = null;
- fKeyDeliver[index] = null;
- }
-
- void deliverEventTo(Event evt, Container deliverTo)
- {
- if (deliverTo == null)
- {
- postEvent(evt);
- }
- else
- {
- deliverTo.postEvent(evt);
- }
- }
-
- boolean doTab(Component current, int tabModifiers)
- {
- int sze = tabbed.size();
-
- if (sze > 0 && (tabModifiers == 0 || tabModifiers == Event.SHIFT_MASK) )
- {
- Component tabTo = null;
- int idx = tabbed.indexOf(current);
- int iCurrent = idx;
-
- if (idx == -1)
- {
- Component c = current;
-
- while (c != this && idx == -1)
- {
- idx = tabbed.indexOf(c);
- c = c.getParent();
- }
- }
-
- if (idx == -1)
- {
- if (tabModifiers == 0)
- {
- doTab((Component) tabbed.lastElement(), tabModifiers);
- }
- else
- {
- doTab((Component) tabbed.firstElement(), tabModifiers);
- }
-
- return true;
- }
- else
- {
- int tabFromIdx = idx;
-
- while (true)
- {
- if (tabModifiers == 0) // regular tab
- {
- if (++idx == sze)
- {
- idx = 0;
- }
- }
- else
- {
- if (--idx == -1)
- {
- idx = sze - 1;
- }
- }
-
- if (tabFromIdx == idx) // looped through all items and none were enabled
- {
- break;
- }
-
- try
- {
- tabTo = (Component) tabbed.elementAt(idx);
-
- if (tabTo.isEnabled() && tabTo.isVisible())
- {
- //Check if user wants to tab only to TextComponents
- if (!bOnlyTabToTextComponents || tabTo instanceof TextComponent)
- {
- tabTo.requestFocus();
-
- if (tabTo instanceof TextComponent)
- {
- TextComponent tc = (TextComponent) tabTo;
- tc.selectAll();
- }
-
- Component tabFrom = (Component) tabbed.elementAt(iCurrent);
- Event eLostFocus = new Event(tabFrom, Event.LOST_FOCUS, null);
- tabFrom.postEvent(eLostFocus);
-
- if (tabFrom instanceof TextComponent)
- {
- TextComponent tf = (TextComponent) tabFrom;
- tf.select(0,0);
- }
-
- tabTo = (Component) tabbed.elementAt(idx);
- Event eGotFocus = new Event(tabTo, Event.GOT_FOCUS, null);
- tabTo.postEvent(eGotFocus);
-
- return true;
- }
- }
- }
- catch (ArrayIndexOutOfBoundsException e)
- {
- }
- }
- }
- }
-
- return false;
- }
- }
-